// 交叉类型
// 交叉类型是将多个类型合并为一个类型
// 类型A & 类型B

type A = {
    id: number
    name: string
  }
  
  type B = {
    age: number
  }
  
  type A1 = {
    sex: "男" | "女"
    type: "Admin" | "Vip" | "Client"
  }
  
  type C = A & B & A1;
  type D = A | B;
  type E = string | number | boolean
  // type F = string & number & boolean // never
  
  const obj5: C = {
    id: 1,
    name: "jack",
    age: 20,
    sex: "男",
    type: "Admin"
  }
  
  const obj6: D = {
    id: 1,
    name: "jack",
    age: 20,
  }
  
  // 类型断言
  // 简单来说，TS会根据上下文进行推测，但是有时候我们可以人为干涉，确定某一个类型
  // 类型断言就是告诉TS编译器，”我知道我在做什么，这里没有类型安全问题，我自己来掌控“
  // 允许我们使用更宽松的方式处理类型问题
  // 语法：1、值 as 类型 或 2、<类型>值
  let someValue: any = "this is a string";
  // 建议使用as的方式，因为react中的jsx语法和<类型>值方式会产生歧义
  let strLength1 = (someValue as string).length;
  let strLength2 = (<string>someValue).length;
  console.log("=====================");
  console.log(strLength1, strLength2);
  console.log("=====================");
  // 非空断言
  // 当你确定某个值不是null或者undefined时候，可以直接使用非空断言
  // 语法：值!
  let maybeString: string | undefined = "hello";
  let defineString = maybeString!;
  
  function getRandom(length?:number) { 
    if (!length || length <= 0) { 
      return undefined
    }
  
    return Math.random().toString(36).slice(-length);
  }
  let s = getRandom(6);
  (s as string).charAt(0)
  // 非空断言
  s!.charAt(0);
  
  type Box = {
    id: number
    name: string
  }
  
  function getBox(): Box | undefined { 
    if (Math.random() > 0.5) {
      return {
        id: 1,
        name: "box"
      } as Box
    }
    return undefined
  }
  
  function createProduction(box: Box) {
    // todos...
  }
  createProduction(getBox()!)
  createProduction(getBox() as Box)
  
  // 比如常见的DOM操作
  // const inputDom = document.querySelector("input");
  // inputDom!.addEventListener("change", e => { 
  //   console.log((e.target as HTMLInputElement).value);
  // });
  
  // 可选链操作符 ES2020 node14+
  // 语法：对象?.属性名
  interface Address{
    city?: string
    street?: string
  }
  
  interface Student{
    name: string
    address?: Address
  }
  
  const student: Student = {
    name: "jack",
    address: {
      city: "成都",
      // street:"人民大街"
    }
  }
  let street = student.address?.street;
  console.log(street)
  